package com.party.mobile.web.controller.wechat;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.party.authorization.annotation.Authorization;
import com.party.common.constant.Constant;
import com.party.common.constant.WechatConstant;
import com.party.common.redis.StringJedis;
import com.party.common.utils.PartyCode;
import com.party.common.utils.StringUtils;
import com.party.core.model.WechatPayCode;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.wechatPlatform.WechatOpenMember;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.wechatPlatform.IWechatMerchantService;
import com.party.core.service.wechatPlatform.IWechatOpenMemberService;
import com.party.mobile.biz.currentUser.CurrentUserBizService;
import com.party.mobile.biz.wechat.WechatBizService;
import com.party.mobile.biz.wechat.WechatOpenMemberBizService;
import com.party.mobile.web.dto.AjaxResult;
import com.party.mobile.web.dto.login.output.CurrentUser;
import com.party.mobile.web.dto.wechat.input.AccessTokenResponse;
import com.party.mobile.web.dto.wechat.input.AccessTokenResponseWithError;
import com.party.mobile.web.dto.wechat.input.JsConfigSign;
import com.party.mobile.web.dto.wechat.input.UserInfoResponse;
import com.party.mobile.web.dto.wechat.output.OathorizeUrlOutput;
import com.party.mobile.web.dto.wechat.output.WechatJsConfg;
import com.party.mobile.web.utils.VerifyCodeUtils;
import com.party.mobile.web.utils.WechatJsUtils;
import com.party.mobile.web.utils.aes.AES;
import com.party.notify.wechatNotify.service.IWechatNotifyService;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.crypto.BadPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;

/**
 * 微信控制层
 * party
 * Created by wei.li
 * on 2016/9/24 0024.
 */
@Controller
@RequestMapping("/wechat/wechat")
public class WechatController {

    @Autowired
    private WechatBizService wechatBizService;

    @Autowired
    private StringJedis stringJedis;

    @Autowired
    private IWechatOpenMemberService wechatOpenMemberService;

    @Autowired
    private IWechatMerchantService wechatMerchantService;

    @Autowired
    private WechatOpenMemberBizService wechatOpenMemberBizService;

    @Autowired
    private IWechatNotifyService wechatNotifyService;

    @Autowired
    private CurrentUserBizService currentUserBizService;

    @Autowired
    private IMemberGroupService memberGroupService;

    protected static Logger logger = LoggerFactory.getLogger(WechatTestController.class);

    /**
     * 获取微信授权地址
     * @param redirectUri 重定向url
     * @return 微信授权url
     */
    @ResponseBody
    @RequestMapping("/getOathorizeUrl")
    public AjaxResult getOathorizeUrl(String redirectUri){

        //数据验证
        if (Strings.isNullOrEmpty(redirectUri)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "重定向地址不能为空");
        }

        String oathorizeUrl;
        try {
            oathorizeUrl = wechatBizService.getOathorizeUrl(redirectUri);
        } catch (UnsupportedEncodingException e) {
            return AjaxResult.error(PartyCode.OATHORIZEURL_ERROR, "生成授权url错误");
        }

        OathorizeUrlOutput oathorizeUrlOutput = new OathorizeUrlOutput();
        oathorizeUrlOutput.setUrl(oathorizeUrl);
        return AjaxResult.success(oathorizeUrlOutput);
    }

    /**
     * 获取微信授权地址（普通授权）（多商户）
     * @param redirectUri 重定向url
     * @return 微信授权url
     */
    @ResponseBody
    @RequestMapping("/getBaseOathorizeUrl")
    public AjaxResult getBaseOathorizeUrl(String redirectUri, String memberId){

        //数据验证
        if (Strings.isNullOrEmpty(redirectUri)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "重定向地址不能为空");
        }
        
        String oathorizeUrl;
        try {
            oathorizeUrl = wechatOpenMemberBizService.getOathorizeUrl(redirectUri, memberId);
        } catch (UnsupportedEncodingException e) {
            return AjaxResult.error(PartyCode.OATHORIZEURL_ERROR, "生成授权url错误");
        }

        OathorizeUrlOutput oathorizeUrlOutput = new OathorizeUrlOutput();
        oathorizeUrlOutput.setUrl(oathorizeUrl);
        return AjaxResult.success(oathorizeUrlOutput);
    }

    /**
     * 获取授权地址, base的
     * @param redirectUri
     * @param wechatOpenMemberId
     * @return
     */
    @ResponseBody
    @RequestMapping("/getSnsapiBaseCodeUrl")
    public AjaxResult getSnsapiBaseCodeUrl(String redirectUri, String wechatOpenMemberId, String wechatMerchantId, Integer deployType) {
        //数据验证
        if (Strings.isNullOrEmpty(redirectUri)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "重定向地址不能为空");
        }
        if (Strings.isNullOrEmpty(wechatOpenMemberId)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "wechatOpenMemberId不能为空");
        }
        if (Strings.isNullOrEmpty(wechatMerchantId)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "wechatMerchantId不能为空");
        }
        if (null == deployType){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "deployType不能为空");
        }
        String oathorizeUrl = null;
        try {
            WechatOpenMember wechatOpenMember = wechatOpenMemberService.get(wechatOpenMemberId);
            if (null == wechatOpenMember || null == wechatOpenMember.getAuthorizerAppid()) {
                return AjaxResult.error(WechatPayCode.NO_SUCH_WECHAT_OPEN_MEMBER, "系统找不到该公众号, 请重新配置微信账号或者授权");
            }
            String appId = wechatOpenMember.getAuthorizerAppid();
            if (1 == deployType) {
                oathorizeUrl = wechatBizService.getSnsapiBaseCodeUrl(redirectUri, appId, deployType, wechatOpenMemberId, wechatMerchantId);
            } else {
                oathorizeUrl = wechatBizService.getAuthorizationSnsapiBaseCodeUrl(redirectUri, appId, deployType, wechatOpenMemberId, wechatMerchantId);
            }
        } catch (Exception e) {
            logger.error("生成Url错误", e);
            return AjaxResult.error(PartyCode.OATHORIZEURL_ERROR, "生成授权url错误");
        }
        OathorizeUrlOutput oathorizeUrlOutput = new OathorizeUrlOutput();
        oathorizeUrlOutput.setUrl(oathorizeUrl);
        return AjaxResult.success(oathorizeUrlOutput);
    }

    @ResponseBody
    @RequestMapping("/getSnsapiBaseOpenId")
    public AjaxResult getSnsapiBaseOpenId(String wechatOpenMemberId, String code, Integer deployType) {
        //数据验证
        if (Strings.isNullOrEmpty(code)){
            return AjaxResult.error(WechatPayCode.AUTHORIZATION_CODE_IS_EMPTY, "授权会话码code为空, 请关闭页面重新打开");
        }
        if (Strings.isNullOrEmpty(wechatOpenMemberId)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "wechatOpenMemberId不能为空");
        }
        String openId = null;
        try {
            AccessTokenResponseWithError r = null;
            WechatOpenMember wechatOpenMember = wechatOpenMemberService.get(wechatOpenMemberId);
            if (null == wechatOpenMember || null == wechatOpenMember.getAuthorizerAppid()) {
                return AjaxResult.error(WechatPayCode.NO_SUCH_WECHAT_OPEN_MEMBER, "系统找不到该公众号, 请重新配置微信账号或者授权");
            }
            String appId = wechatOpenMember.getAuthorizerAppid();
            if (0 == deployType) {
                r = wechatBizService.getSnsapiBaseOpenIdInAuthorization(appId, code);
            } else {
                r = wechatBizService.getSnsapiBaseOpenId(appId, code);
            }
            if (null == r || null == r.getOpenid()) {
                return AjaxResult.error(WechatPayCode.AUTHORIZATION_OPENID_IS_EMPTY, "授权获取openId为空, 请关闭页面重新打开");
            }
            openId = r.getOpenid();
        } catch (Exception e) {
            logger.error("获取微信openId信息错误", e);
            return AjaxResult.error(PartyCode.OPEN_ID_ERROR, "获取微信openId信息错误");
        }
        return AjaxResult.success((Object) openId);
    }

    /**
     * 获取微信用户信息
     * @param code 会话码
     * @param request 请求参数
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping(value = "/getOpenId")
    public AjaxResult getOpenId(String code, HttpServletRequest request){
        //数据验证
        if (Strings.isNullOrEmpty(code)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "会话码code不能为空");
        }

        AccessTokenResponse accessTokenResponse = wechatBizService.acccessToken(code, new MemberGroup());
        if (null == accessTokenResponse){
            return AjaxResult.error(PartyCode.OPEN_ID_ERROR, "获取微信openId信息错误");
        }

        //缓存openId
        stringJedis.setValue(code, accessTokenResponse.getOpenid());
        return AjaxResult.success(accessTokenResponse);
    }
    
    /**
     * 获取微信用户信息（多商户）
     * @param code 会话码
     * @param request 请求参数
     * @param memberId 业务发布者
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping(value = "/getOpenId2")
    public AjaxResult getOpenId2(String code, HttpServletRequest request, String memberId){
        //数据验证
        if (Strings.isNullOrEmpty(code)){
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "会话码code不能为空");
        }
        AccessTokenResponse accessTokenResponse = wechatOpenMemberBizService.acccessToken(code, memberId);
        if (null == accessTokenResponse || StringUtils.isEmpty(accessTokenResponse.getOpenid())){
            return AjaxResult.error(PartyCode.OPEN_ID_ERROR, "获取微信openId信息错误");
        }

        //缓存openId
        stringJedis.setValue(code, accessTokenResponse.getOpenid());
        return AjaxResult.success(accessTokenResponse);
    }


    /**
     * 获取微信小程序openid
     *
     * @param code    会话码
     * @param request 请求参数
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping({"getXcxOpenId"})
    public AjaxResult getXcxOpenId(String code, HttpServletRequest request) {
        //数据验证
        if (Strings.isNullOrEmpty(code)) {
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "会话码code不能为空");
        }
        JSONObject openIdResponse = wechatBizService.getXcxOpenId(code, null);
        if (null == openIdResponse) {
            return AjaxResult.error(PartyCode.OPEN_ID_ERROR, "获取微信openId信息错误");
        }
        return AjaxResult.success(openIdResponse);
    }

    /**
     * 获取微信小程序openid
     *
     * @param code   会话码
     * @param appId  appid
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping({"code2session"})
    public AjaxResult code2session(String code, String appId) {
        //数据验证
        if (Strings.isNullOrEmpty(code)) {
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "会话码code不能为空");
        }
        JSONObject openIdResponse = wechatBizService.getXcxOpenId(code, appId);
        if (null == openIdResponse) {
            return AjaxResult.error(PartyCode.OPEN_ID_ERROR, "获取微信openId信息错误");
        }
        return AjaxResult.success(openIdResponse);
    }

    /**
     * 解析加密数据
     *
     * @param encryptedData 加密数据
     * @param iv            加密算法的初始向量
     * @param sessionKey    session_key
     * @return
     */
    @ResponseBody
    @RequestMapping({"decodeUserInfo", "decodeEncryptedData"})
    public AjaxResult decodeUserInfo(String encryptedData, String iv, String sessionKey) {
        try {
            logger.info("解析加密数据請求參數：——encryptedData：{}，iv：{}，sessionKey：{}", encryptedData, iv, sessionKey);
            AES aes = new AES();
            byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
            if (null != resultByte && resultByte.length > 0) {
                String userInfo = new String(resultByte, "UTF-8");
                logger.info("解析加密数据响应结果：{}", userInfo);
                JSONObject jsonObject = JSONObject.parseObject(userInfo);
                return AjaxResult.success(jsonObject);
            } else {
                throw new Exception("為空的情況解析加密数据异常");
            }
        } catch (BadPaddingException e) {
            logger.error("BadPaddingException解析加密数据异常：——encryptedData：" + encryptedData + ",iv：" + iv + ";sessionKey：" + sessionKey, e);
            return AjaxResult.error(110, "");
        } catch (Exception e) {
            logger.error("Exception解析加密数据异常：——encryptedData：" + encryptedData + ",iv：" + iv + ";sessionKey：" + sessionKey, e);
            return AjaxResult.error(100, "");
        }
    }
    /**
     * 获取js 接口初始化函数
     * @param url 当前页面url
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping("/getJsConfig")
    public AjaxResult getJsConfig(String url){

        WechatJsConfg wechatJsConfg = new WechatJsConfg();
        String nonceStr = VerifyCodeUtils.RandomString(WechatConstant.RANDOM_LENGTH);//获取随机数
        String timeStamp = Long.toString(System.currentTimeMillis() / 1000);
        wechatJsConfg.setAppId(wechatOpenMemberService.getSystem().getAuthorizerAppid());
        wechatJsConfg.setNonceStr(nonceStr);
        wechatJsConfg.setTimestamp(timeStamp);

        //签名
        String ticket = wechatOpenMemberService.getSystem().getTicket();
        JsConfigSign jsConfigSign = new JsConfigSign();
        jsConfigSign.setTimestamp(timeStamp);
        jsConfigSign.setUrl(url);
        jsConfigSign.setNoncestr(nonceStr);
        jsConfigSign.setTicket(ticket);

        String sign = WechatJsUtils.sign(jsConfigSign);
        wechatJsConfg.setSignature(sign);
        return AjaxResult.success(wechatJsConfg);
    }
    
    /**
     * 获取js 接口初始化函数（多商户）
     * @param url 当前页面url
     * @param memberId 业务发起者
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping("/getJsConfig2")
    public AjaxResult getJsConfig2(String url, String memberId) {
        try {
            logger.info("orgId：{}", memberId);
            if (Strings.isNullOrEmpty(memberId)) {
                return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "业务发布者memberId不能为空");
            }

            WechatJsConfg wechatJsConfg = new WechatJsConfg();
            String nonceStr = VerifyCodeUtils.RandomString(WechatConstant.RANDOM_LENGTH);//获取随机数
            String timeStamp = Long.toString(System.currentTimeMillis() / 1000);

            // 获取绑定商户
            String authorizerAppid = wechatMerchantService.getAppid(memberId);
            if (null != authorizerAppid) {
                wechatJsConfg.setAppId(authorizerAppid);
            } else {
                wechatJsConfg.setAppId(wechatOpenMemberService.getSystem().getAuthorizerAppid());
            }
            wechatJsConfg.setNonceStr(nonceStr);
            wechatJsConfg.setTimestamp(timeStamp);

            //签名
            String ticket = wechatOpenMemberService.getSystem().getTicket();
            JsConfigSign jsConfigSign = new JsConfigSign();
            jsConfigSign.setTimestamp(timeStamp);
            jsConfigSign.setUrl(url);
            jsConfigSign.setNoncestr(nonceStr);
            jsConfigSign.setTicket(ticket);

            String sign = WechatJsUtils.sign(jsConfigSign);
            wechatJsConfg.setSignature(sign);
            logger.info("orgId：{}，返回结果信息：{}", memberId, JSONObject.toJSONString(wechatJsConfg));
            return AjaxResult.success(wechatJsConfg);
        } catch (Exception e) {
            logger.error("getJsConfig2异常", e);
            return AjaxResult.error(100, "初始化方法异常");
        }
    }

    @ResponseBody
    @RequestMapping("/getTestConfig")
    public AjaxResult getTestConfig(String url, String wechatOpenMemberId) {
        WechatJsConfg wechatJsConfg = new WechatJsConfg();
        String nonceStr = VerifyCodeUtils.RandomString(WechatConstant.RANDOM_LENGTH);//获取随机数
        String timeStamp = Long.toString(System.currentTimeMillis() / 1000);

        // 获取绑定商户
        WechatOpenMember wechatOpenMember = wechatOpenMemberService.get(wechatOpenMemberId);
        if (null == wechatOpenMember || null == wechatOpenMember.getAuthorizerAppid()) {
            return AjaxResult.error(WechatPayCode.NO_SUCH_WECHAT_OPEN_MEMBER, "系统找不到该公众号, 请重新配置微信账号或者授权");
        }
        String authorizerAppid = wechatOpenMember.getAuthorizerAppid();
        if (null != authorizerAppid) {
            wechatJsConfg.setAppId(authorizerAppid);
        } else {
            wechatJsConfg.setAppId(wechatOpenMemberService.getSystem().getAuthorizerAppid());
        }
        wechatJsConfg.setNonceStr(nonceStr);
        wechatJsConfg.setTimestamp(timeStamp);

        //签名
        String ticket = wechatOpenMemberService.getSystem().getTicket();
        JsConfigSign jsConfigSign = new JsConfigSign();
        jsConfigSign.setTimestamp(timeStamp);
        jsConfigSign.setUrl(url);
        jsConfigSign.setNoncestr(nonceStr);
        jsConfigSign.setTicket(ticket);

        String sign = WechatJsUtils.sign(jsConfigSign);
        wechatJsConfg.setSignature(sign);
        logger.info("wechatOpenMemberId：{}，返回结果信息：{}", wechatOpenMemberId, JSONObject.toJSONString(wechatJsConfg));
        return AjaxResult.success(wechatJsConfg);
    }

    /**
     * 微信长连接转短连接
     * @param url 请求参数
     * @return 返回连接
     */
    @ResponseBody
    @RequestMapping("/longToShort")
    public AjaxResult longToShort(String url){
        WechatOpenMember wechatOpenMember = wechatOpenMemberService.getSystem();
        String resultUrl = wechatBizService.longToShort(url, wechatOpenMember.getAuthorizerAccessToken());
        return AjaxResult.success(resultUrl);
    }

    /**
     * 根据openid获取用户信息
     * @param openId 用户唯一标识
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping(value = "/userInfo")
    public AjaxResult userInfo(String openId, String accessToken){
        try {
            UserInfoResponse userInfoResponse = wechatBizService.userInfo(openId, accessToken);
            return AjaxResult.success(userInfoResponse);
        } catch (Exception e) {
            logger.error("获取微信用户信息异常", e);
            return AjaxResult.error();
        }
    }

    /**
     * 设置关注连接
     * @param openId openid
     * @param url url
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping(value = "setAttentionUrl")
    public AjaxResult setAttentionUrl(String openId, String url, String partnerId, HttpServletRequest request) {
        try {

            if (StringUtils.isNotBlank(url)) {
                url = url.replace("&qrFlag=true", "");
            }
            if (StringUtils.isNotEmpty(partnerId)) {
                MemberGroup member = memberGroupService.get(partnerId);
                stringJedis.setValue(Constant.ATTENTION_PARTNER_NAME + openId, member.getRealname(), 86400);
            }
            stringJedis.setValue(Constant.ATTENTION_URL_KEY + openId, url, 86400);
            logger.info("缓存的关注连接key{}, value{}", Constant.ATTENTION_URL_KEY + openId, url);
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("设置关注链接异常", e);
            return AjaxResult.error(100, "设置关注链接异常");
        }
    }

    /**
     * 微信是否订阅
     * @param memberId 商户编号
     * @param openid openid
     * @return 交互数据
     */
    @ResponseBody
    @RequestMapping(value = "isSubscribe")
    public AjaxResult isSubscribe(String memberId, String openid){
        try {
           boolean isSubscribe = wechatBizService.isSubscribe(memberId, openid);
           return AjaxResult.success(isSubscribe);
        } catch (Exception e) {
            logger.error("isSubscribe异常", e);
            return AjaxResult.error(100, "异常");
        }
    }

    /**
     * 初始化运动打卡小程序微信账号
     * @return
     */
    @ResponseBody
    @RequestMapping("initSignXcxAccount")
    public AjaxResult initSignXcxAccount() {
        wechatBizService.initSignXcxWechatAccount();
        return AjaxResult.success();
    }

    /**
     * 初始化相册小程序微信账号
     * @return
     */
    @ResponseBody
    @RequestMapping("initPhotoXcxAccount")
    public AjaxResult initPhotoXcxAccount() {
        wechatBizService.initPhotoXcxAccount();
        return AjaxResult.success();
    }

    /**
     * 存储formId
     *
     * @param request
     * @param formId  formId
     * @return
     */
    @ResponseBody
    @Authorization
    @RequestMapping("insertXcxFormId")
    public AjaxResult insertXcxFormId(HttpServletRequest request, String formId) {
        try {
            CurrentUser currentUser = currentUserBizService.getCurrentUser(request);
            wechatNotifyService.insertXcxFormId(currentUser.getId(), formId, "");
            return AjaxResult.success();
        } catch (Exception e) {
            logger.error("存储formId异常", e);
            return AjaxResult.error();
        }
    }

    /**
     * 初始化争分小程序
     * @return
     */
    @ResponseBody
    @RequestMapping("initScoreXcxAccount")
    public AjaxResult initScoreXcxAccount() {
        wechatBizService.initScoreXcxAccount();
        return AjaxResult.success();
    }



    /**
     * @Description: 初始化行知公社小程序
     * @Param: []
     * @return: com.party.mobile.web.dto.AjaxResult
     * @Author: Hua Qunhao
     * @Date: 2019/8/13
     */
    @ResponseBody
    @RequestMapping("initIntegralXcxAccount")
    public AjaxResult initIntegralXcxAccount() {
        wechatBizService.initIntegralXcxAccount();
        return AjaxResult.success();
    }
}
